

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.*;

import javax.swing.Box;
import javax.swing.JApplet;


import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSpinner;

import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;

public class SatApplet extends JApplet implements Runnable {

	//intial values
	double planet_leftx,planet_lefty,planet_r=10;
	double orbit_leftx,orbit_lefty,orbit_major=400,orbit_minor=300;//2a 2b
	double sat_leftx,sat_lefty,sat_leftx_prev,sat_lefty_prev,sat_r=8;
	
	double m_e = (5.9736*Math.pow(10,24));	//10 to power 22 in kg
	double m_s = 1 *Math.pow(10,3); //10 to power 22  in kg
	double speed_s = 1.022*1000 ; //in m/s
	double G = 6.67*Math.pow(10, -11);	//*10^-11 N*(m/Kg)
	double r = 382440*1000;	//in m
	double v_initial = (1.022)*1000;		//in m/s
	double v_theta = (1.022/1.414)*1000;	//in m/s
	double v_r = (1.022/1.414)*1000;		//in m/s
	double l,E,c;
	double ecc;
	Ellipse2D.Double circle3,circle4;
	int flag=0;
	boolean flag_p = true;
	
	double fact = 2.4; // r0_in/r0_new  a calculated using r0_in and a taken actually
	double scale = 1900000;
	
	double r1;
	int w=200,h=200;
	int count = 0;
	Thread runner=null;
	int flaggg=0;
	int flag2=0;
	double[][] position = new double[360][2];
	Dimension appletSize;
	int appletHeight,appletWidth;
	
	Label eneLabel, momLabel, vradLabel, vthetaLabel, vradnewLabel, vthetanewLabel;
	Label enenewLabel, momnewLabel;
	TextField eneText, momText, vradText, vthetaText, vradnewText, vthetanewText, enenewText, momnewText;
	JSeparator separator;
	Button StartButton, PauseButton;
	private boolean test;

	private boolean appStart;
	private double newvrad;
	private double newvtheta;
	protected boolean newval=false;
	private double rot_angle=0;
	private int rot_point;
	private double new_b;
	private double new_a;
	private double r0_in;
	private double center_x;
	private int center_y;
	private double E_new=0;
	private double l_new=0;
	private Button ResetButton;
	private boolean restartflag=false;
	private int te=1;
	int f=1;
	int fsb=0;   //flag to disable and enable start button
	int fpb=0;
	Box button_bar;
	Button InstrButton;
	JTextComponent _imaginary,_instructions;
	private int heig=200;
	private int weig=200;
	private int pawid;
	private int pahei;
	int time =10;
	int time1 = 395;
	
	
	public void init(){
		compute();
		makeUI();
		test=true;
	}
	
	
	
	public void makeUI() {
		
		appletHeight = getHeight();
	    appletWidth = getWidth();
		
	    Color  panelbg=Color.LIGHT_GRAY;
        Color  panelfg=Color.white;
		Color  buttonfg=Color.black;
		

		
		Panel pa = new Panel();
		add("North",pa);
		pa.setBackground(Color.BLACK);
		
		System.out.println("pahei is:"+pahei);
		
	    Label appletLabel = new Label("Motion of Satellite around Planet");
	    appletLabel.setForeground(Color.RED);
	    appletLabel.setFont(new Font("Times New Roman", Font.BOLD, 20));
	    
	    pa.add(appletLabel);
	   
	    Panel pa1 = new Panel(new GridLayout(11, 2));
	    add("East",pa1);
	    pa1.setBackground(Color.BLACK);
	    	    
	    
	    Label satLabel = new Label("Satelite");
	    satLabel.setForeground(Color.WHITE);
	    satLabel.setFont(new Font("Times New Roman", Font.BOLD, 20));
	    Label plaLabel = new Label("Earth");
	    plaLabel.setForeground(Color.WHITE);
	    plaLabel.setFont(new Font("Times New Roman", Font.BOLD, 20));
	   
	    Dimension tempDim1=new Dimension(appletWidth/25, appletHeight/12);
	    tempDim1.setSize(1*appletWidth/20, appletHeight/12);
	    
	    Button rb = new Button("");
	    rb.setBackground(Color.BLUE);
	    rb.setSize(appletHeight/100, appletHeight/100);
	    
	    Button gb = new Button("");
	    gb.setBackground(Color.YELLOW);
	    pa1.add(gb);
	    pa1.add(satLabel);
	    pa1.add(rb);
	    pa1.add(plaLabel);
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    pa1.add(Box.createRigidArea(tempDim1));
	    
	   
	    
		vradLabel = new Label("v_rad:", Label.LEFT);
		vthetaLabel = new Label("v_theta:", Label.LEFT);
		eneLabel = new Label("Energy(10^8):", Label.LEFT);
		momLabel = new Label("Momentum(10^14):", Label.LEFT);
		vradnewLabel = new Label("v_rad_new:", Label.LEFT);
		vthetanewLabel = new Label("v_theta_new:", Label.LEFT);
		enenewLabel = new Label("New Energy(10^8):", Label.LEFT);
		momnewLabel = new Label("New Momentum(10^14):", Label.LEFT);
		
		vradText = new TextField(String.valueOf(v_r));
		vthetaText = new TextField(String.valueOf(v_theta));
		vradText.setEditable(false);
		vthetaText.setEditable(false);
		
		eneText = new TextField(String.valueOf(0.001*Math.round(E*1000/Math.pow(10, 8))));
		momText = new TextField(String.valueOf(0.001*Math.round(l*1000/Math.pow(10, 14))));
		eneText.setEditable(false);
		momText.setEditable(false);
		
		if(!newval){
			vradnewText = new TextField("  ");
			vthetanewText = new TextField("  ");
		}
		
		enenewText = new TextField("    ");
		momnewText = new TextField("    ");
		enenewText.setEditable(false);
		momnewText.setEditable(false);
		
		StartButton = new Button("Start");
		PauseButton = new Button("Change Orbit");
		ResetButton = new Button("Reset");
		InstrButton = new Button("Instructions");
				
		System.out.println("vr: "+newvrad);
		System.out.println("vthe: "+newvtheta);
		
		Panel p1 = new Panel(new GridLayout(2, 1));
		Panel p2 = new Panel(new GridLayout(2, 1));
		Panel p3 = new Panel(new GridLayout(2, 1));
		Panel p4 = new Panel(new GridLayout(2, 1));
		Panel p5 = new Panel(new GridLayout(1, 3));
		Panel p6 = new Panel(new GridLayout(2, 1));
		Panel p7 = new Panel(new GridLayout(2, 1));
		Panel p8 = new Panel(new GridLayout(2, 1));
		Panel p9 = new Panel(new GridLayout(2, 1));
		Panel p10 = new Panel(new GridLayout(1, 1));
		
		p1.add(vradLabel);
		p1.add(vthetaLabel);
		p2.add(vradText);
		p2.add(vthetaText);
		p3.add(eneLabel);
		p3.add(momLabel);
		p4.add(eneText);
		p4.add(momText);

		p5.add(ResetButton);
		p5.add(StartButton);
		p5.add(PauseButton);
		
		p6.add(vradnewLabel);
		p6.add(vthetanewLabel);
		p7.add(vradnewText);
		p7.add(vthetanewText);
		p8.add(enenewLabel);
		p8.add(momnewLabel);
		p9.add(enenewText);
		p9.add(momnewText);
		p10.add(InstrButton);
		
		Dimension tempDim=new Dimension(appletWidth/25, appletHeight/12);
		//final Box button_bar = Box.createHorizontalBox();
		Panel button_bar =new Panel();
		button_bar.setBackground(Color.WHITE);
		
	    
	    tempDim.setSize(1*appletWidth/20, appletHeight/12);
			      
		button_bar.add(p1);
		tempDim.setSize(appletWidth/100, appletHeight/100);

		button_bar.add(p2);
		button_bar.add(Box.createRigidArea(tempDim));
		button_bar.add(p3);

		button_bar.add(p4);
		button_bar.add(Box.createRigidArea(tempDim));
		button_bar.add(p5, Component.CENTER_ALIGNMENT);
		button_bar.add(Box.createRigidArea(tempDim));
		button_bar.add(p6);

		button_bar.add(p7);
		button_bar.add(Box.createRigidArea(tempDim));
		button_bar.add(p8);

		button_bar.add(p9);
		button_bar.add(Box.createRigidArea(tempDim));
		button_bar.add(p10, Component.CENTER_ALIGNMENT);
		
		System.out.println("ewe:"+E);
		
		enenewText.setText(String.valueOf(0.001*Math.round(E_new*1000/Math.pow(10, 8))));
		//enenewText.updateUI();
		//enenewText.setEditable(true);
		
		momnewText.setText(String.valueOf(0.001*Math.round(l_new*1000/Math.pow(10, 14))));
		
		System.out.println("-"+tempDim);
		System.out.println("--"+p1.getPreferredSize());
		button_bar.validate();
		add("South",button_bar);
		button_bar.validate();
		getContentPane().setVisible(true);
		
		StartButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				if(appStart || fsb == 0)
					return;
			
				appStart = true;
				//makeUI();
				if(newval){
					newvrad = Double.parseDouble(vradnewText.getText().toString());
					newvtheta = Double.parseDouble(vthetanewText.getText().toString());
					System.out.println("here:"+newvtheta);
					calculate(newvtheta,newvrad);
				}
				
				System.out.println("sadfsf =="+E);
				System.out.println("qwerty =="+l);
				enenewText.setText(String.valueOf(0.001*Math.round(E*1000/Math.pow(10, 8))));
				momnewText.setText(String.valueOf(0.001*Math.round(l*1000/Math.pow(10, 14))));
				createnewthread();
				
			}
		});
		
		PauseButton.addActionListener(new ActionListener()
		{	
			
			@Override
			public void actionPerformed(ActionEvent arg0)
			{
				if(fpb==1)
					return;
				runner.stop();
				System.out.println("thread stop");
				appStart = false;
				newval=true;
				fsb=1;
				fpb=1;
				System.out.println(count);
			}
		});	
			
		ResetButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				runner.stop();
				m_e = (5.9736*Math.pow(10,24));
				m_s = 1 *Math.pow(10,3);
				speed_s = 1.022*1000 ;
				G = 6.67*Math.pow(10, -11);
				r = 382440*1000;
				v_initial = (1.022)*1000;
				v_theta = (1.022/1.414)*1000;
				v_r = (1.022/1.414)*1000;
				fsb=0;
				fpb=0;
				flag_p = true;
				flag=0;
				fact = 2.4;
				scale = 1900000;
				flaggg=0;
				rot_angle=0;
				count = 0;
				restartflag = true;
				test=true;
				vradnewText.setText("  ");
				vthetanewText.setText("  ");
				enenewText.setText(String.valueOf(0.0));
				momnewText.setText(String.valueOf(0.0));
				compute();
				
				te = 2;
				appStart = true;
				cordinates(w, h);
			
				System.out.println("before");
			
				createnewthread();
					
				System.out.println("after");
			}
		});
		
		InstrButton.addActionListener(new ActionListener()
		{	
			@Override
			public void actionPerformed(ActionEvent arg0)
			{
				String msg = "<html><b>Instructions to use this applet</b> <br/>" +
						"<body>In this animation a satellite is orbiting the earth. Its orbit can be changed by altering the satellite's velocities.<br/> The satellite's velocity can be changed at any point on the orbit.<br/>" +
						"<ul><li>V_rad :  <b>Radial Velocity</b></li>" +
						"<li>V_theta : <b>Tangential Velocity</b></li>" +
						"<li>V_rad_new : <b>New Radial Velocity</b></li>" +
						"<li>V_theta_new : <b>New Tangential Velocity</b></li></ul>" +
						"<br/>"+
						"The velocity can be altered by entering pressing <b>'Change orbit'</b>, entering the new values of radial velocity and tangential velocity, and then pressing <b>'Start'</b>."+
						"<br/>"+
						"After pressing 'start' the satellite moves along the new orbit. The energy, angular momentum on the old and new orbit are both displayed as well.<br/><br/>"+
						"'Only the original orbit can be changed in this applet. This applet has not been designed to once again change the new orbit thus obtained.<br/><br/>"+
						"SI Units are used"+
						"</body></html>";
				        JLabel label = new JLabel(msg);
				        label.setFont(new Font("serif", Font.PLAIN, 14));
				JOptionPane.showMessageDialog(_instructions,label,"Instructions",JOptionPane.INFORMATION_MESSAGE);
			}
		});
		
	}



	public void compute(){
		
		l = m_s*r*v_theta;	//in 10 to power 28
		System.out.println("l_old:"+l);
		
		E = (-(G*m_e*m_s)/r) + (m_s*v_theta*v_theta)/2 + (m_s*v_r*v_r)/2;
		System.out.println("E_old:"+E);
		
		c = G*m_e*m_s;
		ecc = Math.sqrt(1+((2*E*l*l)/(m_s*c*c)));
		
		r0_in = (l*l)/(m_s*c);
		 
		r0_in = r0_in/scale;
		System.out.println("r0_old:"+r0_in);
		System.out.println("scale:"+scale);
		
		System.out.println("ecc_old:"+ecc);
		orbit_major = (r0_in/(1+ecc))/(1-ecc);
		orbit_minor = Math.sqrt((orbit_major*orbit_major)*(1-(ecc*ecc)));
		
		orbit_major = orbit_major * 2;
		orbit_minor = orbit_minor * 2;
		
	}
		
	public void cordinates(int he, int we)
	{	
			count = 0;
						
			if(flag_p)
			{
				center_x = he/2-orbit_major*ecc/2;
		     	center_y = we/2;
			}
			
			while(count<360)
			{
				double angle = count * Math.PI/180.0;
				
				r1 =r0_in/(1-ecc*Math.cos(angle));
				
				position[count][0] = center_x+r1*Math.cos(angle)-sat_r/2;
				position[count][1] = center_y+r1*Math.sin(angle)-sat_r/2;
				count++;			
				
			}
			count =0;
			
						
		}
		
	
	
	public void display(int height,int width){
		
		if(flag_p == true)
		{
		planet_leftx = height/2-planet_r/2-orbit_major*ecc/2;
		planet_lefty = width/2-planet_r/2;
		
		
		}
	
		double center_x = planet_leftx + (orbit_major*ecc/2);
		double center_y = planet_lefty;
		
		orbit_leftx = center_x -(orbit_major/2);
		orbit_lefty = center_y - (orbit_minor/2);

		flag2=1;
	}
	
	public void draw_circle(Graphics2D g2) {
		
		
		if(flag==1){	
			
			g2.setColor(Color.BLACK);
			
			sat_leftx_prev=sat_leftx_prev-(sat_r/2);
			sat_lefty_prev=sat_lefty_prev-(sat_r/2);
			circle4 =new Ellipse2D.Double(sat_leftx_prev,sat_lefty_prev,sat_r,sat_r);
			
			g2.fill(circle4);
			
		}	
		if(count<360){
			
			sat_leftx = position[count][0];
			sat_lefty = position[count][1];
			sat_leftx_prev = sat_leftx;
			sat_lefty_prev = sat_lefty;
			count++;
		}
		if(count==360){
			count = 0;
		}
		
		flag=1;
		
		sat_leftx=sat_leftx-(sat_r/2);
		sat_lefty=sat_lefty-(sat_r/2);
		circle3 =new Ellipse2D.Double(sat_leftx,sat_lefty,sat_r,sat_r);
		g2.setColor(Color.YELLOW);
		g2.fill(circle3);
				
	}
		
	public void paint(Graphics g){
		
		
				
		if(test)
		{
			
			super.paintComponents(g);
			Graphics2D g3 = (Graphics2D) g;
			g3.setColor(Color.BLACK);
			g3.fillRect(0, 0, w, h);
			System.out.println("widt is "+w+"height is"+h);

			test=false;
			
		}
		Graphics2D g2 = (Graphics2D) g;
		appletSize = this.getSize();
		
		display(w,h);
		
		if(flaggg==0)
			{
				
				flaggg=1;
			}	
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
				
		Ellipse2D.Double circle1 =new Ellipse2D.Double(planet_leftx,planet_lefty,planet_r,planet_r);
		g2.setColor(Color.blue);
		g2.fill(circle1);
				
		draw_orbit(g2,rot_angle);
		
		draw_circle(g2);	
		
		double r_dis = r0_in/(1-ecc*Math.cos(((360-count)*Math.PI)/180));
		r_dis = r_dis*scale;
		double vthet = l/(m_s*r_dis);
		
		vthetaText.setText(String.valueOf(vthet));
		
		double vradi = Math.sqrt((E+(c/r_dis) - (m_s*vthet*vthet/2))*2/m_s);
		
		if(count >=0 && count<180)
		{
			vradi = -vradi;
		}
		vradText.setText(String.valueOf(vradi));	
		
	}
		
		
	void draw_orbit(Graphics2D g2, double angle){
		int h1,w1;
		
		h1 = appletSize.height;
		w1 = appletSize.width;
		
		if(h1!=200&&w1!=200){
		
		Ellipse2D.Double orb =new Ellipse2D.Double(orbit_leftx,orbit_lefty,orbit_major,orbit_minor);
		
		g2.rotate(rot_angle,planet_leftx,planet_lefty);
		
		g2.setColor(Color.green);
		g2.draw(orb);
		}
	}
	
	public void calculate(double vthetanew, double vradnew)
	{
		count--;
		flag_p=false;
		appletSize = this.getSize();
		int wid = appletSize.width;
		int hei = appletSize.height;
		
		r1 =r0_in/(1-ecc*Math.cos(((count)*Math.PI)/180));
		
		r1 = r1*scale;
				
		double l_new = m_s*r1*vthetanew;
		
		double E_new = (-(G*m_e*m_s)/r1) + (m_s*vthetanew*vthetanew)/2 + (m_s*vradnew*vradnew)/2;
		
		System.out.println("new E: "+E_new);
		c = G*m_e*m_s;
		
		double ecc_new = Math.sqrt(1+((2*E_new*l_new*l_new)/(m_s*c*c)));
		
		r1 = r1/scale;
		double r0_new = (l_new*l_new)/(m_s*c);
		r0_new = r0_new/scale;
		double arg = (r1-r0_new)/(r1*ecc_new);
				
		double temp_angle1 =(((count)*Math.PI)/180 - Math.acos(arg));
		double temp_angle2 = (((count)*Math.PI)/180 + Math.acos(arg));
		
		new_a = (r0_new/(1+ecc_new))/(1-ecc_new);
		new_b = Math.sqrt((new_a*new_a)*(1-(ecc_new*ecc_new)));
		
		double x11 = r1* Math.cos(((count)*Math.PI)/180); 
		double y11 = r1* Math.sin(((count)*Math.PI)/180);
		
		
		System.out.println("x11=="+x11);
		System.out.println("y11=="+y11);
		
		double n11 = (2*x11) - 2*ecc_new*ecc_new*x11*Math.cos(temp_angle1)*Math.cos(temp_angle1);
		double n21 = -2*r0_new*ecc_new*Math.cos(temp_angle1) - ecc_new*ecc_new*y11*Math.sin(2*temp_angle1);
		double d11 = (2*y11) - 2*ecc_new*ecc_new*x11*Math.sin(temp_angle1)*Math.sin(temp_angle1);
		double d21 = -2*r0_new*ecc_new*Math.sin(temp_angle1) - ecc_new*ecc_new*x11*Math.sin(2*temp_angle1);
		
		double slope1 = -(n11 + n21)/(d11+d21); 
		System.out.println("slope1 is: "+slope1);
						
		double v_x11 = (vradnew*Math.cos((((count)*Math.PI)/180))) - (vthetanew*Math.sin((((count)*Math.PI)/180)));
		double v_y11 = (vradnew*Math.sin((((count)*Math.PI)/180))) + (vthetanew*Math.cos((((count)*Math.PI)/180)));
		
		double v_rat1 = v_y11/v_x11;
				
		System.out.println("v_x11 is: "+v_x11);
		System.out.println("v_y11 is: "+v_y11);
		
		System.out.println("v_rat11 is: "+v_rat1);
		
		double check_value = (-x11*new_b*new_b)/(y11*new_a*new_a);
		System.out.println("check: "+check_value);
		
		double n12 = (2*x11) - 2*ecc_new*ecc_new*x11*Math.cos(temp_angle2)*Math.cos(temp_angle2);
		double n22 = -2*r0_new*ecc_new*Math.cos(temp_angle2) - ecc_new*ecc_new*y11*Math.sin(2*temp_angle2);
		double d12 = (2*y11) - 2*ecc_new*ecc_new*x11*Math.sin(temp_angle2)*Math.sin(temp_angle2);
		double d22 = -2*r0_new*ecc_new*Math.sin(temp_angle2) - ecc_new*ecc_new*x11*Math.sin(2*temp_angle2);
		
		double slope2 = -(n12+n22)/(d12+d22); 
		System.out.println("slope2 is: "+slope2);
		
		if(Math.abs(v_rat1 - (slope1)) > Math.abs(v_rat1 - (slope2)))
		{
			rot_angle = temp_angle2;
			System.out.println("in temp2==");
		}
		else
		{
			System.out.println("in temp1==");
			rot_angle = temp_angle1;
		}
		
		System.out.println("temp1==="+temp_angle1*180/(Math.PI));
		System.out.println("temp2==="+temp_angle2*180/(Math.PI));
		
		
		orbit_major = 2*new_a;
		orbit_minor = 2*new_b;
		
		r0_in = r0_new;
		l=l_new;
		E=E_new;
		ecc=ecc_new;
		
		appletSize = this.getSize();
		int h1 = this.getHeight();
		int w1 = this.getWidth();
		
		
		cordinates(w1,h1);
		
	}
	
	@Override
	public void run() {
		System.out.println("run");
		while(runner!=null){
			
			try {
				
				double r5 =r0_in/(1-ecc*Math.cos(((count)*Math.PI)/180));
				//System.out.println("r5 is: "+r5);
				time =(int)(r5*r5/(300));
				
				if(time == time1)
				{
					if(count>90 && count<=180 && time!=0)
					{
						time = time-1;
						time1=time;
					}
					else if(count>180 && count<=270 && time!=0)
					{
						time = time+1;
						time1=time;
					}
				}
							
				
				System.out.println("time is: "+time);			
				
				Thread.sleep(time);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			appletSize = this.getSize();
			int h1 = this.getHeight();
			int w1 = this.getWidth();
			
			
			if(h != h1|| w != w1)
			{
				
				h = h1;
				w = w1;
				test=true;
				cordinates(w1,h1);
				
			}
			repaint();
		}
		
		
	}
	
	public void start()
	{
		
		runner = new Thread(this);
		runner.start();
		System.out.println("fddss");
		System.out.println(runner.getId());
	}
	
	public void stop() {

	     if ( runner != null && runner.isAlive() )
	         runner.stop();
	    runner = null;
	}
	
	protected void createnewthread() {
		// TODO Auto-generated method stub
		runner = new Thread(this);
		runner.start();
	}

}
